/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.metasketch.model.loader;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import java.util.StringTokenizer;

/**
 * 
 * @author guilhermegrg
 */
public class ModelReader implements IGraphFileReader {

	public Map<String, GraphNode> nodes = new HashMap<String, GraphNode>();
	List<GraphNode> simpleNodes = new ArrayList<GraphNode>();
	// List<GraphRelationship> relationshipNodes = new
	// ArrayList<GraphRelationship>();
	IGraphDatabase graphdb;

	// private boolean insideHumanActivity;
	// private ParseNode humanActivityNode;

	public ModelReader(IGraphDatabase graphdb) {
		this.graphdb = graphdb;
	}

	public final IGraphDatabase readFile(File file) throws Throwable {

		nodes.clear();
		simpleNodes.clear();
		// relationshipNodes.clear();

		// graphdb.cleanup();
		// graphdb.shutdown();

		// graphdb.startup();
		// graphdb.cleanup();

		Scanner scanner = new Scanner(file);
		try {
			// GraphNode parent = null;

			// first use a Scanner to get each line
			recursiveRead(scanner, null);

		} finally {
			// ensure the underlying stream is always closed
			scanner.close();
		}

		// now process all nodes into graph database
		for (GraphNode parseNode : simpleNodes) {
			graphdb.storeNode(parseNode);
		}

		return graphdb;

	}

	private void recursiveRead(Scanner scanner, GraphNode parent)
			throws Exception {
		while (scanner.hasNextLine()) {

			String line = scanner.nextLine();

			if (line.contains("</")) {
				return;
			}

			GraphNode node = null;

			try {

				node = buildModel(getProperties(line), parent);
				if (node == null)
					continue;

			} catch (Throwable t) {
				t.printStackTrace();
				continue;
			}

			if (!line.contains("/>")) {
				GraphNode currentParent = node;
				recursiveRead(scanner, currentParent);
			}

		}
	}

	private Map<String, String> getProperties(String line) {

		Map<String, String> properties = new HashMap<String, String>();

		int indexOf = line.indexOf("<");

		String tag = null;

		if (indexOf >= 0) {
			tag = line.substring(indexOf+1);
			tag = tag.substring(0, tag.indexOf(' '));
			tag = removeNamespace(tag);
			properties.put("tag", tag);
		}

		String property;
		String name = null;
		String value;
		StringTokenizer tokenizer = new StringTokenizer(line);
		boolean joinMode = false;
		String longValue = null;
		while (tokenizer.hasMoreTokens()) {
			property = tokenizer.nextToken();

			// System.out.println(property);

			int index = property.indexOf('=');
			if (index < 0 && !joinMode) {
				continue;
			} else if (index < 0 && joinMode) {

				int dashIndex = property.indexOf('\"');
				if (dashIndex > 0) {
					value = property.substring(index + 1).replace("\"", "");
					longValue += ' ' + value;
					properties.put(name, longValue);
					// System.out.println(name + " -> " + longValue);
					joinMode = false;
					continue;
				}

				longValue += ' ' + property;

				continue;
			}

			longValue = "";
			name = property.substring(0, index);
			value = property.substring(index + 1).replaceFirst("\"", "");

			name = removeNamespace(name);
			value = removeNamespace(value);

			if (value.indexOf('\"') > 0) {
				value = value.replace("\"", "");
				value = value.replace(">", "");
				properties.put(name, value);
				// System.out.println(name + " -> " + value);
				continue;
			}

			joinMode = true;

			longValue += value;
			// properties.put(name, value);
		}

		return properties;

	}

	private String removeNamespace(String text) {
		if (text.contains(":")) {
			return text.substring(text.indexOf(':') + 1);
		}
		return text;

	}

	private GraphNode buildModel(Map<String, String> properties,
			GraphNode parent) throws Exception {

		String id = properties.get("id");
		// if (id == null) {
		// throw new Exception(" Node has no ID !!!");
		//
		// }

		if (id == null && parent == null) {
			return null;
			// throw new Exception(" Invalid node !!! No id and no parent !");
		}

		if (id != null && nodes.get(id) != null) {
			throw new Exception(" Node " + id
					+ " already Exists !!! Can't create again !!!!");
		}

		String type = properties.get("type");
		// if (type == null) {
		// throw new Exception(" Node has no type !!!");
		//
		// }

		String tag = properties.get("tag");
		// if (type == null) {
		// throw new Exception(" Node has no tag !!!");
		//
		// }

		String name = properties.get("name");

		// GraphNode node = null;
		GraphNode endNode;

		GraphNode node = new GraphNode(id, type);
		node.setTag(tag);
		node.setName(name);

		node.getProperties().putAll(properties);

		Set<String> names = properties.keySet();

		// // test for target and source indications for
		// for (String name : names) {
		// if (name.contains("contained") || name.equalsIgnoreCase("action")) {
		//
		// StringTokenizer tokenizer = new StringTokenizer(
		// properties.get(name));
		//
		// while (tokenizer.hasMoreTokens()) {
		// String child = tokenizer.nextToken();
		// node.getChildrenIds().add(child);
		// }
		// }
		//
		// }

		if (parent != null)
			parent.addChild(node);
		else {
			simpleNodes.add(node);
		}

		if (id != null)
			nodes.put(id, node);

		return node;

	}

	public IGraphDatabase getGraphdb() {
		return graphdb;
	}
	// public void setGraphdb(GraphDatabase graphdb) {
	// this.graphdb = graphdb;
	// }
}
